#!/usr/bin/perl -w

# Simple Source metrics for C++
# Taj Sun Apr 26 03:31:00 EST 1998
# $Id: cxxmetric 363 2004-09-14 19:14:55Z ewald-arnold $

$bigblank = 0;
$bigcommt = 0;
$bigstrcount = 0;
$bigstrsize = 0;
$bigtotal = 0;
$numfiles = 0;

$blocklen = 0;
$numblocks = 0;
$blockdepth = 0;
$blockstart = 0;
$blockmin = -1;
$blockmax = 0;
@blenlist = ();

sub processFile
{
	my( $file ) = @_;
	$blank  = 0;
	$comment  = 0;
	$total  = 0;
	$incomment  = 0;
	$strcount = 0;
	$strsize = 0;

	open( SOURCE, "$file" ) || 
		die "cxxmetric.pl: Couldn't read from $file.\n";

	while( <SOURCE> ) {
		$total++;

		if ( /^\s*$/ ) {
			$blank++;
			next;
		}

		if ( m#^\s*//# ) {
			$comment++;
			next;
		}

		if ( /{/ ) {
			# block start
			$blockdepth += s/{/{/g;

			$blockstart = $. if $blockdepth  == 1;
		}

		if ( /}/ ) {
			# block end

			$blockdepth -= s/}/}/g;

			if( $blockdepth == 0 ) {
				my $thisblocklen = $. - $blockstart;
				push @blenlist, $thisblocklen;
				
				$blocklen += $thisblocklen;
				$numblocks++;

				if( $blockmax < $thisblocklen ) {
					$blockmax = $thisblocklen;
				}

				if ( $blockmin == -1 
					|| $blockmin > $thisblocklen ) {
					$blockmin = $thisblocklen;
				}
			}
		}	

		$start	= 0;
		$stop	= 0;	

		if ( m#/\*# ) {
			$start = 1;
		}
		
		if( m#\*/# ) {
			$stop = 1;
		}

		if( $start ) {
			$incomment = 1 unless $stop;
			$comment++;
		}
		elsif ( $stop ) {
			$comment++;
			$incomment = 0;
		}
		elsif ( $incomment ) {
				$comment++;
		}
		else {
				my $line = $_;
				countStrings( $line );
		}
	}

	$code = $total - ($comment + $blank );
	$bigtotal += $total;
	$bigcommt += $comment;
	$bigblank += $blank;
	$bigstrcount += $strcount;
	$bigstrsize += $strsize;
	
	$stravglen = $strcount ? ($strsize / $strcount) : 0;

	write;
}


sub countStrings
{
		my $line = shift;

		foreach my $string ( split( /("[^"]*)"/, $line ) ) {
				next unless $string =~ /^\"/;

				$strcount++;
				$strsize += length( $string ) - 1;
		}
}

sub pct
{
	my( $top, $bottom ) = @_;

	return 0 if $bottom == 0;

	return int(( $top * 100 ) / $bottom);
}

foreach $file ( @ARGV ) {
	processFile( $file );
	++$numfiles;
}

$total =  $bigtotal;
$comment= $bigcommt;
$blank =  $bigblank;
$code  = $bigtotal - ($bigcommt + $bigblank );
$file = "Total";

print "\n";
write;

print "\nPercentage Code:\t" , pct( $code, $total ),"%\n";
print "Percentage Comment:\t" , pct( $comment, $total ),"%\n";
print "Percentage Blank:\t" , pct( $blank, $total ),"%\n";
print "Percentage Cmt/Code:\t" , pct( $comment, $code ),"%\n";
print "Average Code/File:\t" , int($code/$numfiles)," lines\n" 
	unless $numfiles == 0;

if ( $numblocks > 0 ) {
	$avg = int( $blocklen / $numblocks );
	@blenlist = sort @blenlist;
	$median = $blenlist[ int( $numblocks / 2 )];
print<<EOF;

Blocks:\t$numblocks
\tLengths (lines):\tmin: $blockmin\tmax: $blockmax\tmed: $median\taverage: $avg
EOF
}

$bigstravglen = $bigstrcount ? int($bigstrsize / $bigstrcount) : 0;

print<<EOF;
Strings:\t$bigstrcount
\tSize (bytes):\ttotal: $bigstrsize\taverage: $bigstravglen
EOF

exit;

format STDOUT_TOP =
 Lines	Code	Comment	 Blank	Strs   AvgLen File
 ------	-------	-------- ------	------ ------ ------

.

format STDOUT =
@######	@######	@######	@######	@######	@######	@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$total, $code, $comment, $blank, $strcount, $stravglen, $file
.
